/**
 * 日历组件
 * @param {*} option 
 * @returns 
 */
function scCalendar(){
    var listeners = {};

    var _year = null;
    var _month = null;
    var _day = null;

    var _hour = null;
    var _minute = null;
    var _second = null;

    var _type = "date";
    var _view = null;

    const ATTR_VALUE = "d-value";
    const ATTR_DATE = "d-date";
    const ATTR_CASCADE = "d-cascade";
    const ATTR_ACTION = "d-action";

    /**
     * 获取组件名称
     * @returns 
     */
    this.getName = function(){
        return "calendar";
    }

    /**
     * 创建日历视图
     * @param {*} option
     */
    this.createView = function(option){
        option = option ? option : {}

        _type = option.type ? option.type : _type;

        if(!option.date){
            option.date = new Date();
        }else{
            option.date = new Date(option.date);
        }

        var currentDate = option.date;

        _year = currentDate.getFullYear();
        _month = currentDate.getMonth() + 1;
        _day = currentDate.getDate();

        _view = document.createElement("div");
        _view.classList.add("s-component-calendar");

        var html = "";

        if(_type == "date" || _type == "datetime"){
            html += "<div class='scc-date-picker'>";
            html += "<div class='scc-title'>";
            html += "<span class='scc-arrow' " + ATTR_ACTION + "='prevYear'>«</span>";
            html += "<span class='scc-arrow' " + ATTR_ACTION + "='prevMonth'>‹</span>";
            html += "<span class='scc-content'>" + _year + "年" + _month + "月</span>";
            html += "<span class='scc-arrow' " + ATTR_ACTION + "='nextMonth'>›</span>";
            html += "<span class='scc-arrow' " + ATTR_ACTION + "='nextYear'>»</span>";
            html += "</div>";

            html += "<table>";

            html += "<thead>";
            html += "<tr class='scc-sub-title'>";
            html += "<th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th>";
            html += "</tr>";
            html += "</thead>";

            html += "<tbody>";
            
            //计算一个月有多少天
            var dayCount = new Date(_year, _month, 0).getDate();
            //获取指定年月的第一个星期的数值
            var weekNum = new Date(_year, _month).getDay();

            html += "<tr>";

            var clazz = "";

            for (var day = 1; day <= dayCount; day++){
                //如果该月的第一天不是星期日
                if(weekNum && day == 1){
                    html += "<td colspan = '"+ weekNum +"'></td>";
                }

                clazz = day == _day ? "class='active'" : "";
                html += "<td " + ATTR_DATE + "='" + _year + "," + _month + "," + day + "' " + clazz + ">" + day + "</td>";

                //如果星期六不是该月的最后一天，则换行
                if (weekNum == 6 && day != dayCount){
                    html += "</tr><tr>";
                }
                //该月的最后一天
                else if(day == dayCount) {
                    html += "</tr>";
                }

                weekNum = (weekNum + 1 > 6) ? 0 : weekNum + 1;
            }

            html += "</tbody>";
            html += "</table>";
            html += "</div>";
        }

        if(_type == "datetime" || _type == "time"){
            _hour = currentDate.getHours();
            _minute = currentDate.getMinutes();
            _second = currentDate.getSeconds();

            html += "<div class='scc-time-picker'>";

            html += "<div class='scc-time-head'>"
            html += "</div>";

            html += "<div style='display: flex;flex-direction: row;'>";
            html += "<div class='scc-time-body'>"
            //时
            var hour = complementZero(_hour);
            html += "<ul>";
            html += "<li class='scc-time-frag'>";
            html += "<input type='text' " + ATTR_CASCADE + "='hour' value='"+hour+"' maxlength=2/>"
            html += "</li>";
            html += "</ul>";
            html += "<span>:</span>";
            //分
            var minute = complementZero(_minute);
            html += "<ul>";
            html += "<li class='scc-time-frag'>";
            html += "<input type='text' " + ATTR_CASCADE + "='minute' value='"+minute+"' maxlength=2/>"
            html += "</li>";
            html += "</ul>";
            html += "<span>:</span>";
            //秒
            var second = complementZero(_second);
            html += "<ul>";
            html += "<li class='scc-time-frag'>";
            html += "<input type='text' " + ATTR_CASCADE + "='second' value='"+second+"' maxlength=2/>"
            html += "</li>";
            html += "</ul>";

            html += "</div>";
            html += "<a class='sc-time-keyboard-link' d-keyboard='1'>键盘</a>";
            html += "</div>";

            html += "<div class='scc-time-keyboard'>"
            for(var i = 0; i < 10; i++){
                html += "<div class='scc-tk-btn' d-key='"+i+"'>"+i+"</div>";
            }
            html += "</div>";
            
            html += "<div class='scc-time-foot'>"
            html += "<button class='scc-th-btn' "+ATTR_ACTION+"='selectedDate'>确定</button>"
            html += "</div>";

            html += "</div>";
        }

        _view.innerHTML = html;
        
        bindEvent.call(this, _view);

        return _view;
    }

    /**
     * 将年月日拼接成指定格式的字符串
     * @param {*} year 
     * @param {*} month 
     * @param {*} day 
     */
    var _formatter = function(year, month, day, hour, minute, second){
        var str = "";

        if(year != null && month != null && day != null){
            str = year + "-" + complementZero(month) + "-" + complementZero(day);
        }

        var join = str.length > 0 ? " " : "";

        if(hour != null && minute != null && second != null){
            str += join + complementZero(hour);
            str += ":" + complementZero(minute);
            str += ":" + complementZero(second);
        }

        return str;
    }

    /**
     * 给单个数字前面补0
     * @param {*} number 
     */
    var complementZero = function(number){
        return number.toString().length > 1 ? number : "0" + number;
    }

    /**
     * 给元素添加事件监听
     * @param {*} element 
     */
    var bindEvent = function(element){
        var inputs = element.querySelectorAll("input[type='text']")
        var curInput = null;

        for(let i = 0; i < inputs.length; i++){
            inputs[i].addEventListener("focus", (e)=>{
                curInput = e.target;
            });

            inputs[i].addEventListener("dblclick", (e)=>{
                e.stopPropagation();
            });

            inputs[i].addEventListener("input", (e)=>{
                e.stopPropagation();

                let name = e.target.getAttribute(ATTR_CASCADE);

                if(name == "hour"){
                    _hour = e.target.value;
                }else if(name == "minute"){
                    _minute = e.target.value;
                }else if(name == "second"){
                    _second = e.target.value;
                }
            });
        }

        curInput = inputs[0];

        element.addEventListener("mousedown", (e)=>{
            e.stopPropagation();
            
            var evt = {
                sourceEvent: e
            };

            var format = this.formatter ? this.formatter : _formatter;

            if(e.target.getAttribute(ATTR_DATE)){
                evt.value = e.target.getAttribute(ATTR_DATE).split(",");

                _year = evt.value[0];
                _month = evt.value[1];
                _day = evt.value[2];

                if(_type != "datetime"){
                    if(!validateTime()) return;

                    evt.value = format(_year, _month, _day, _hour, _minute, _second);

                    if(listeners["mousedown"]){
                        listeners["mousedown"](evt);
                    }
                }else{
                    var td = _view.querySelector(".scc-date-picker td.active");
                    if(td){
                        td.classList.remove("active");
                    }
                    e.target.classList.add("active");
                }
            }else if(e.target.getAttribute(ATTR_ACTION)){

                var action = e.target.getAttribute(ATTR_ACTION);

                if(action == "selectedDate"){
                    if(!validateTime()) return;
                    if(_type == "datetime"){
                        evt.value = format(_year, _month, _day, _hour, _minute, _second);
                    }else if(_type == "time"){
                        evt.value = format(null, null, null, _hour, _minute, _second);
                    }
                }else{
                    if(action == "prevMonth"){
                        var month = _month - 1;
                        if(month < 1){
                            _year--;
                            _month = 12;
                        }else{
                            _month--;
                        }
                    }else if(action == "nextMonth"){
                        var month = _month + 1;
                        if(month > 12){
                            _year++;
                            _month = 1;
                        }else{
                            _month++;
                        }
                    }else if(action == "prevYear"){
                        _year--;
                    }else if(action == "nextYear"){
                        _year++;
                    }
    
                    evt.view = this.createView({
                        date: format(_year, _month, _day, _hour, _minute, _second)
                    });
                    evt.action = "refreshView";
                }

                if(listeners["mousedown"]){
                    listeners["mousedown"](evt);
                }
            }else if(e.target.getAttribute(ATTR_CASCADE)){
                var elements = _view.querySelectorAll(".scc-time-frag");
                for(var i = 0; i < elements.length; i++){
                    elements[i].classList.remove("active");
                }

                e.target.classList.add("active");
            }else if(e.target.getAttribute("d-key")){
                var key = e.target.getAttribute("d-key");
                var element = _view.querySelector(".scc-time-frag.active");
                var val = curInput.value
                
                val = val.substr(1, 1) + key;

                curInput.value = val;

                var cascade = curInput.getAttribute(ATTR_CASCADE);
                if(cascade == "hour"){
                    _hour = val;
                }else if(cascade == "minute"){
                    _minute = val;
                }else if(cascade == "second"){
                    _second = val;
                }
            }else if(e.target.getAttribute("d-keyboard")){
                var keyboard = _view.querySelector(".scc-time-keyboard");
                if(keyboard.classList.contains("active")){
                    keyboard.classList.remove("active");
                }else{
                    keyboard.classList.add("active");
                }
            }else{
                return;
            }
        });
    }

    /**
     * 检验时间
     * @returns 
     */
    var validateTime = function(){
        if(parseInt(_hour) > 23){
            alert("小时格式错误，必须在0-23之间");
            return false;
        }else if(parseInt(_minute) > 59){
            alert("分钟格式错误，必须在0-23之间");
            return false;
        }else if(parseInt(_second) > 59){
            alert("秒格式错误，必须在0-23之间");
            return false;
        }
        return true;
    }

    /**
     * 给组件添加监听
     * @param {*} eventType 事件类型
     * @param {*} callback 回调函数
     */
    this.addEventListener = function(eventType, callback){
        listeners[eventType] = callback;
    }

}